// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rbchat.logic.chat_friend.vv;

import android.app.Activity;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.eva.android.widget.TimerViewWrapper;
import com.eva.android.widget.WidgetUtils;
import com.eva.android.widget.WidgetUtils.ToastType;
import com.eva.android.widget.alert.AlertDialog;
import com.vc.core.P2PController;
import com.vc.core.VcConstants;
import com.x52im.rbchat.MyApplication;
import com.x52im.rbchat.R;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;
import com.x52im.rbchat.cache.ImageCacheLoader;
import com.x52im.rbchat.logic.chat_friend.utils.MessageHelper;
import com.x52im.rbchat.logic.chat_root.model.VoipRecordMeta;

import net.x52im.mobileimsdk.android.utils.MBThreadPoolExecutor;
import net.x52im.rainbowav.sdk.AccountManager;
import net.x52im.rainbowav.sdk.iface.ILoginEventListener;
import net.x52im.rainbowav.sdk.iface.IReceiveEventListener;
import net.x52im.rainbowav.sdk.util.NetworkUtil;

import java.text.MessageFormat;

/**
 * 实时语音聊天包装实现类.
 * 
 * @author Jack Jiang, 2013-11-15
 */
public class RealTimeVoiceWrapper extends VoiceAloneProvider implements IReceiveEventListener, IRealTimeVoiceWrapper
{
	private final static String TAG = RealTimeVoiceWrapper.class.getSimpleName();
	
	private boolean mReceive;  // 是应答还是发起请求
	private int chatType = VcConstants.AUDIO;  // 1语音 2视频
	private long toAccount;    // 对方帐号
	
	/** 是否正在通话中. 本标识在开始通话后被设置、结束通知后被重置 */
	private static boolean talking = false;
	/** UI组件：好友头像 */
	private ImageView viewAvatar = null;
	/** UI组件：计时显示 */
	private TextView viewTimer = null;
	/** UI组件：实时音视频控制子布局 */
	private ViewGroup layoutOfRealTimeVoiceOpr = null;
	/** UI组件：实时音视频结束按钮 */
	private View btnEndRealTimeVoice = null;
	
	/** 包装实现类：计时器 */
	private TimerViewWrapper timerViewWrapper = null;
	
	private LoginEventImpl loginEventImpl = null;
	
	public RealTimeVoiceWrapper(Activity parentActivity)
	{
		super(parentActivity);
		
		loginEventImpl = new LoginEventImpl();
		
		initViews();
		initListeners();
	}
	
    /**
     * UI初始化方法.
     */
	private void initViews()
	{
		viewAvatar = parentActivity.findViewById(R.id.chatting_list_view_realtime_voice_avatarView);
		viewTimer = parentActivity.findViewById(R.id.chatting_list_view_realtime_voice_timerView);
		layoutOfRealTimeVoiceOpr = parentActivity.findViewById(R.id.chatting_list_view_realtime_voice_opr_sublayout);
		btnEndRealTimeVoice = parentActivity.findViewById(R.id.chatting_list_view_realtime_voice_endBtn);
		
		timerViewWrapper = new TimerViewWrapper(parentActivity){
			/**
			 * 子类请重写此方法，实现计时时间变动的ui展现等.<br>
			 * 本方法默认什么也不做.
			 * 
			 * @param hh_mm_ssStr hh:mm:ss格式的时长字符串
			 */
			@Override
			protected void timerChanged(String hh_mm_ssStr)
			{
				viewTimer.setText(hh_mm_ssStr);
			}
		};
	}
	
	/**
	 * UI监听器初始化方法.
	 */
	private void initListeners()
	{
		btnEndRealTimeVoice.setOnClickListener(v -> stop(true));
	}
	
	/**
	 * 开始语音聊天.
	 * 
	 * @param mReceive
	 * @param friendUid
	 * @param anychat_user_id 本参数只在anychat的音视频框架中有用哦，本类中无意义！
	 * 
	 */
	public void start(boolean mReceive, String friendUid, int anychat_user_id)
	{
		this.mReceive = mReceive;
		// 新音视频聊天中登陆服务器的用户账号就是friendUid哦
		this.toAccount = Long.parseLong(friendUid);
		
		// 初始化音频相关
		init();
		
		int result = -1;
		if(mReceive) {
			//接受请求
			result = VVP2PProvider.getInstance(parentActivity).getP2PController().receiveAction(
					AccountManager.myAccount,toAccount,NetworkUtil.getApn(parentActivity),chatType,0);
//			audioStart();
			if(!audioStart()){
				Toast.makeText(parentActivity, "audioStart fail!", Toast.LENGTH_LONG).show();
//				finish();
				// TODO 音频打开失败的处理！release and return?
			}
		} else {
			//发起请求			
			result = VVP2PProvider.getInstance(parentActivity).getP2PController().requestAction(
					AccountManager.myAccount,toAccount,NetworkUtil.getApn(parentActivity),chatType);
			myController.mMicphone = true;//关闭麦克风，不发数据出去
			myController.mSound = true;//先不开启声音，待对方接收后再放开
		}
		
		//请求/应答失败
		if (result != 0) {
//			Toast.makeText(parentActivity, "Request or receive fail,errorCode="+result, Toast.LENGTH_LONG).show();
			Log.e(TAG, "Request or receive fail,errorCode="+result);
			Log.e(TAG, "action fail, chatType="+chatType);

//			WidgetUtils.showToast(parentActivity, "语音聊天服务器无响应（可能是服务已关闭），本次应答失败！", ToastType.ERROR);
//			
//			// 将界面关掉,add by jack jiang 20150805
//			stopImpl(false);
			//
			release();
			
			return;
		} else {
			// 标记"正在通话中"状态
			talking = true;
			// 显示实时语音聊天ui组件
			layoutOfRealTimeVoiceOpr.setVisibility(View.VISIBLE);

			// 对方的好友信息
			RosterElementEntity friendInfo = MyApplication.getInstance2().getIMClientManager().getFriendsListProvider().getFriendInfoByUid2(friendUid);
			// 显示头像
			if(friendInfo != null) {
				// 确保在主线程中执行
				MBThreadPoolExecutor.runOnMainThread(() -> {
					ImageCacheLoader.loadAvatarImgWithGlide(parentActivity, friendInfo.getUser_uid(), friendInfo.getUserAvatarFileName(), viewAvatar
							, 40, R.drawable.default_avatar_yuan_40_3x, true, false);
				});
			}

			// 通话计时开始
			timerViewWrapper.start();
		}

		P2PController.getInstance().setLoginEventListener(loginEventImpl);
		//注册事件接收器
		VVP2PProvider.getInstance(parentActivity).getP2PController().registryRequestEventListener(this);
	}
	
	/**
	 * 停止语音聊天（如果当前正在聊天中，则本方法将保证弹出一个确认对话框供用户
	 * 确认是否关闭）.
	 * 
	 * @param needSendCloseAction true表示停止时需要发一条通知指令给对方，否则不用
	 * @see #stopNoConfirm(boolean)
	 * @see #isTalking()
	 */
	public void stop(final boolean needSendCloseAction)
	{
		if(isTalking())
		{
			new AlertDialog.Builder(parentActivity)
			.setTitle(parentActivity.getString(R.string.general_prompt))  
			.setMessage(parentActivity.getString(R.string.real_time_chat_end_chatting))
			.setPositiveButton(R.string.general_yes, (dialog, which) -> stopNoConfirm(needSendCloseAction))
			.setNegativeButton(parentActivity.getString(R.string.general_no), null)
			.show(); 
		}
	}
	
	/**
	 * 停止语音聊天（如果当前正在聊天中，则无条件停止，无提示对话框）.
	 * 
	 * @param needSendCloseAction true表示停止时需要发一条通知消息给对方，否则不用
	 * @see #stopImpl(boolean)
	 * @see #isTalking()
	 */
	public void stopNoConfirm(boolean needSendCloseAction)
	{
		if(isTalking())
		{
			// 发出一条音视频聊天记录（这样的话，本地和远端都会有记录的哟）
			MessageHelper.sendVoipRecordMessageAsync(
					// context用全局Application对象，确保消息的发送不依赖于本Activity的生命周期
					MyApplication.getInstance2()
					, String.valueOf(toAccount)
					, new VoipRecordMeta(VoipRecordMeta.VOIP_TYPE_VOICE, VoipRecordMeta.RECORD_TYPE_CHATTING_DURATION, timerViewWrapper.getTotoalSecond())
					, null);

			stopImpl(needSendCloseAction);
		}
	}
	
	/**
	 * 停止语音聊天核心实施方法.
	 * 
	 * @param needSendCloseAction true表示停止时需要发一条通知消息给对方，否则不用
	 */
	private void stopImpl(boolean needSendCloseAction)
	{
		Log.d(TAG, "RealTimeVoiceWrapper.stop begin");
		
		//
		layoutOfRealTimeVoiceOpr.setVisibility(View.GONE);
		
		// !!
		P2PController.getInstance().setLoginEventListener(null);
		
		if(needSendCloseAction)
			VVP2PProvider.getInstance(parentActivity).getP2PController().closeAction(AccountManager.myAccount,toAccount,VcConstants.AUDIO);
		
		
        //如果非正常退出/正常退出，都会触发onDestroy在此处结束
        if(VVP2PProvider.getInstance(parentActivity).getP2PController()!=null)
        {
        	VVP2PProvider.getInstance(parentActivity).getP2PController().unRegistryRequestEventListener(this);        	
        }
		
        //一定要调父类的销毁方法
		release();
		
		//
		talking = false;
		//
		timerViewWrapper.stop();

		Log.d(TAG, "RealTimeVoiceWrapper.stop end");
		
//		整理代码，在stop时要隐藏父类的实时音频布局哦！！
    }

	public boolean isTalking()
	{
		return isTalkingImpl();
	}
    /**
     * 当前是否正在聊天中.
     * <p>
     * 本标识在开始通话后被设置、结束通知后被重置.
     * 
     * @return true表示当前正在通知中，否则不在通话中
     * @see #start(boolean, long)
     * @see #stopImpl(boolean)
     */
	public static boolean isTalkingImpl()
	{
		return talking;
	}
	
    public ViewGroup getLayoutOfRealTimeVoiceOpr()
	{
		return layoutOfRealTimeVoiceOpr;
	}

    //
	private Handler handler = new Handler()
    {
        @Override
        public void handleMessage(Message msg) 
        {
        	Log.d(TAG, "handler.handleMessage|current thread="+Thread.currentThread());
        	
            Bundle data = msg.getData();
            long fromAccount = data.getLong("fromAccount",0);
            switch(msg.what){
                case VcConstants.TYPE_CLOSED_AUDIO_BY_FRIEND:
                	RosterElementEntity ree = MyApplication.getInstance(parentActivity)
                		.getIMClientManager().getFriendsListProvider().getFriendInfoByUid(""+fromAccount);
                	WidgetUtils.showToast(parentActivity
                			, MessageFormat.format(
                					parentActivity.getString(R.string.real_time_chat_has_been_end)
                					, ree == null? "":ree.getNickname()+" ")
//                			, "Lover "+(ree == null? "":ree.getNickname()+" ")+"has been end real time voice."
                			, ToastType.INFO);
                    stopImpl(false);
                    break;
                case VcConstants.TYPE_SWITCH_AUDIO_FRIEND:
                	Log.d(TAG, fromAccount+"已切换到语音通话！");
                    break;
                case VcConstants.TYPE_ACCEPT_AUDIO_BY_FRIEND:
                    audioStart();
                    myController.mMicphone = false;//打开麦克风，开始传数据出去
                    myController.mSound = false;//开启声音，接收对方传过来的声音数据播放
                    Log.d(TAG, "DEBUG："+fromAccount+"接受了请求，语音通话中...");
                    break;
                  //p2p打洞成功
	            case VcConstants.TYPE_CONNECT_P2P_SUCC:
//	            	WidgetUtils.showToast(parentActivity, "Promt: P2P is ok, enjoy it.", ToastType.OK);
	            	Log.d(TAG, "Promt: P2P is ok, enjoy it.");
                    break;
                //p2p连接失败/断开
	            case VcConstants.TYPE_CONNECT_P2P_FAILED:
//                    Toast.makeText(parentActivity, "DEBUG: 与对方p2p连接失败!", Toast.LENGTH_LONG).show();
	            	Log.d(TAG, "DEBUG: 与对方p2p连接失败!");
                    //finish();
                    break;
            }
        }
    };

    @Override
    public void onReceiveEvent(int eventId, long fromAccount, byte[] detail) 
    {
//        if(!isBack)
        {
            Message msg = new Message();
            msg.what = eventId;
            Bundle bundle = new Bundle();
            bundle.putLong("fromAccount",fromAccount);
            bundle.putByteArray("detail",detail);
            msg.setData(bundle);
            handler.sendMessage(msg);
        }
    }
    
    // FIXME: 貌似底层音初步聊天框架没有重登机制（只有心跳，那是两码事），此类还有意义吗？
    private class LoginEventImpl implements ILoginEventListener {
    	@Override
		public void onLoginSucc(long fromAccount, byte[] detail) {
			Log.i(TAG, "【VV1_for_RealtimeVoice】上报服务器成功（后台登陆重试）.");
			AccountManager.myAccount = fromAccount;
			
			// 只有当处于实时音视频时才尝试处理！
			if(isTalkingImpl()) {
				if(NetworkUtil.isNetSupport(parentActivity)) {
//					//** P2P打洞请求（首先尝试P2P打洞哦）
//					VVP2PProvider.getInstance(parentActivity).requestP2P(toAccount);
				}
			}
		}

		@Override
		public void onLoginFail(long fromAccount, byte[] detail) {
	           Log.e(TAG, "【VV1_for_RealtimeVoice】上报服务器失败（后台登陆重试）!");
		}
    }
}
